package com.yn.pet.controller.pc.biz;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Sets;
import com.yn.common.core.redis.RedisCache;
import com.yn.common.exception.ServiceException;
import com.yn.common.utils.DateUtils;
import com.yn.common.utils.SecurityUtils;
import com.yn.common.utils.bean.BeanUtils;
import com.yn.common.utils.poi.ExcelUtil;
import com.yn.pet.bus.entity.DeviceInfo;
import com.yn.pet.bus.entity.DeviceSim;
import com.yn.pet.bus.entity.DeviceSyncSettings;
import com.yn.pet.bus.entity.LocationRealtime;
import com.yn.pet.bus.enums.DeviceStatusEnum;
import com.yn.pet.bus.enums.LocationTypeEnum;
import com.yn.pet.controller.pc.request.DeviceInfoRequest;
import com.yn.pet.controller.pc.request.DeviceInfoUpdateRequest;
import com.yn.pet.controller.pc.request.PetQueryRequest;
import com.yn.pet.controller.pc.response.*;
import com.yn.pet.controller.pc.response.page.DevicePageResponse;
import com.yn.pet.entity.*;
import com.yn.pet.entity.model.LoginAppUser;
import com.yn.pet.enums.DeviceModelEnum;
import com.yn.pet.enums.PetTypeEnum;
import com.yn.pet.server.commons.util.StrUtils;
import com.yn.pet.service.*;
import com.yn.pet.util.AppTokenUtil;
import io.jsonwebtoken.lang.Assert;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
@Slf4j
public class DeviceInfoBizService {

    private final DeviceInfoService deviceInfoService;
    private final PetService petService;
    private final LocationRealtimeService locationRealtimeService;
    private final DeviceSimService deviceSimService;
    private final DeviceSyncSettingsService deviceSyncSettingsService;
    private final RedisCache redisCache;
    private final AppUserService appUserService;

    private final String KEY_PREFIX = "deviceStatus:";

    public IPage<DeviceInfoResponse> pageList(DeviceInfoRequest request) {
        int currentPage = 1;
        int pageSize = 10;
        if (request.getCurrentPage() != null) {
            currentPage = request.getCurrentPage();
        }
        if (request.getPageSize() != null) {
            pageSize = request.getPageSize();
        }

        LambdaQueryWrapper<DeviceInfo> queryWrapper = new LambdaQueryWrapper<DeviceInfo>()
                .like(StringUtils.isNotBlank(request.getImei()), DeviceInfo::getImei, request.getImei())
                .like(StringUtils.isNotBlank(request.getDeviceName()), DeviceInfo::getDeviceName, request.getDeviceName())
                .like(StringUtils.isNotBlank(request.getDeviceModel()), DeviceInfo::getDeviceModel, request.getDeviceModel())
                .like(StringUtils.isNotBlank(request.getFactory()), DeviceInfo::getFactory, request.getFactory())
                .ge(!Objects.isNull(request.getActivateTimeStart()), DeviceInfo::getActivateTime, request.getActivateTimeStart())
                .le(!Objects.isNull(request.getActivateTimeEnd()), DeviceInfo::getActivateTime, request.getActivateTimeEnd())
                .eq(DeviceInfo::getDataStatus, 1);

        Page<DeviceInfo> page = deviceInfoService.page(new Page<>(currentPage, pageSize), queryWrapper);
        return page.convert(deviceInfo -> {
            DeviceInfoResponse deviceInfoResponse = new DeviceInfoResponse();
            BeanUtils.copyBeanProp(deviceInfoResponse, deviceInfo);
            Integer locationType = deviceInfo.getLocationType();
            String locationTypeName = LocationTypeEnum.getName(locationType);
            deviceInfoResponse.setLocationTypeName(locationTypeName);

            return deviceInfoResponse;
        });
    }

    public void saveDeviceInfo(DeviceInfo deviceInfo) {
        String imei = deviceInfo.getImei();
        Assert.hasText(imei, "设备IMEI号不能为空");

        DeviceInfo oldDeviceInfo = deviceInfoService.getByImei(imei);
        if (oldDeviceInfo != null && oldDeviceInfo.getDataStatus() == 1 && !oldDeviceInfo.getDeviceId().equals(deviceInfo.getDeviceId())) {
            throw new RuntimeException("设备IMEI号已存在");
        }
        boolean bn = false;
        if (deviceInfo.getDeviceId() == null) {
            deviceInfo.setCreateTime(new Date());
            deviceInfo.setUpdateTime(new Date());
            deviceInfo.setDataStatus(1);
            deviceInfo.setCreateBy(SecurityUtils.getUsername());
            bn = true;
        }
        deviceInfo.setUpdateTime(new Date());
        deviceInfo.setUpdateBy(SecurityUtils.getUsername());
        deviceInfoService.saveOrUpdate(deviceInfo);

        if (bn){
            //新增设备时 同时新增一条设备报警配置信息
            DeviceSyncSettings deviceSyncSettings = new DeviceSyncSettings();
            deviceSyncSettings.setDeviceId(deviceInfo.getDeviceId());
            deviceSyncSettingsService.save(deviceSyncSettings);

        }
    }

    public void removeDeviceInfo(Set<Long> deviceIdSet) {
        Assert.notEmpty(deviceIdSet, "设备ID不能为空");
        List<Pet> pets = petService.listByDeviceIds(deviceIdSet);
        if (!pets.isEmpty()) {
            throw new RuntimeException("请先解除所选设备下的所有宠物");
        }
        deviceInfoService.removeByIds(deviceIdSet);
    }

    public String importDeviceInfo(MultipartFile file) throws IOException {
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();

        Assert.notNull(file, "文件不能为空");
        InputStream inputStream = file.getInputStream();
        ExcelUtil<DeviceInfoRequest> deviceInfoExcelUtil = new ExcelUtil<>(DeviceInfoRequest.class);
        List<DeviceInfoRequest> deviceInfoRequests = deviceInfoExcelUtil.importExcel(inputStream);
        if (CollectionUtils.isEmpty(deviceInfoRequests)) {
            throw new RuntimeException("请选择导入的文件");
        }
        Set<String> imeiSet = deviceInfoRequests.stream().map(DeviceInfoRequest::getImei).collect(Collectors.toSet());
        List<DeviceInfo> deviceInfoList = deviceInfoService.listByImei(imeiSet);
        Set<String> existImei;
        if (!CollectionUtils.isEmpty(deviceInfoList)) {
            existImei = deviceInfoList.stream().map(DeviceInfo::getImei).collect(Collectors.toSet());
        } else {
            existImei = new HashSet<>();
        }

        Set<DeviceInfo> deviceInfoSet = deviceInfoRequests.stream().filter(item -> !existImei.contains(item.getImei())).map(item -> {
            DeviceInfo deviceInfo = new DeviceInfo();
            BeanUtils.copyBeanProp(deviceInfo, item);
            deviceInfo.setCreateTime(new Date());
            deviceInfo.setUpdateTime(new Date());
            deviceInfo.setDataStatus(1);
            deviceInfo.setCreateBy(SecurityUtils.getUsername());
            deviceInfo.setUpdateBy(SecurityUtils.getUsername());
            return deviceInfo;
        }).collect(Collectors.toSet());
        if (!CollectionUtils.isEmpty(deviceInfoSet)) {
            deviceInfoService.saveBatch(deviceInfoSet);
            for (DeviceInfo deviceInfo : deviceInfoSet) {
                successNum++;
                successMsg.append("<br/>").append(successNum).append("imei ").append(deviceInfo.getImei()).append(" 导入成功");
            }
        }
        if (!CollectionUtils.isEmpty(existImei)) {
            for (String imei : existImei) {
                failureNum++;
                failureMsg.append("<br/>").append(failureNum).append("imei ").append(imei).append(" 已存在");
            }
        }

        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    public DeviceDetailResponse queryById(Long id) {

        AppUser appUser = AppTokenUtil.getAppUser();
        if (appUser == null) {
            throw new RuntimeException("用户不存在");
        }
        log.info("查询设备详情的用户信息appUser：{}", appUser);
        //查询db
        LambdaQueryWrapper<DeviceInfo> queryDeviceInfo = new LambdaQueryWrapper<DeviceInfo>().eq(DeviceInfo::getDeviceId, id);
        DeviceInfo deviceInfo = deviceInfoService.getOne(queryDeviceInfo);
        DeviceDetailResponse response = new DeviceDetailResponse();
        //封装设备基础信息 设备id imei号 ip，端口号，设备名称
        response.setDeviceId(deviceInfo.getDeviceId());
        response.setImei(deviceInfo.getImei());
        response.setDeviceModel(deviceInfo.getDeviceModel());
        response.setServerIp(deviceInfo.getServerIp());
        response.setServerPort(deviceInfo.getServerPort());
        response.setDeviceName(deviceInfo.getDeviceName());

        //pet信息
        Pet pet = petService.getByDeviceIdAndUserId(deviceInfo.getDeviceId(), appUser.getAppUserId());
        if(pet== null){
            throw new RuntimeException("用户未绑定该设备");
        }
        response.setPetType(pet.getPetType());
        response.setPetTypeName(PetTypeEnum.getNameByCode(pet.getPetType()));


        //平台服务信息
        //根据设备id查询设备SIM绑定表查询ICCID
        DeviceSim deviceSim = deviceSimService.getByDeviceId(id);
       /* if (deviceSim == null) {
            throw new RuntimeException("设备未绑定SIM卡");
        }*/
        //激活时间，过期时间，iccid

        if(deviceSim!=null){
            response.setActivateTime(deviceSim.getActivateTime());
            response.setExpireTime(deviceSim.getExpireTime());
            response.setIccid(deviceSim.getIccid());
        }
        //根据设备id去实时位置信息表查到最新位置信息(创建时间降序的第一条数据)
        LambdaQueryWrapper<LocationRealtime> queryLocation = new LambdaQueryWrapper<LocationRealtime>()
                .eq(LocationRealtime::getDeviceId, id)
                .orderByDesc(LocationRealtime::getCreateTime)
                .last("limit 1");
        LocationRealtime realtime = locationRealtimeService.getOne(queryLocation);
        if (realtime == null) {
            throw new RuntimeException("设备未启用");
        }
        response.setDeviceStatus(deviceInfo.getDeviceStatus());
        response.setDeviceStatusName(DeviceStatusEnum.getByCode(deviceInfo.getDeviceStatus()).getName());

        response.setLocationTime(realtime.getReceiveTime());
        response.setLongitude(realtime.getLongitude());
        response.setLatitude(realtime.getLatitude());
        response.setDetailedLocation(realtime.getDetailedLocation());
        response.setLocationType(realtime.getLocationType());

        //手机号，头像
        response.setBindPhone(appUser.getPhone());
        response.setNickName(appUser.getNickname());

        log.info("查询设备详情的封装的联系人名称1：appUser.getNickname()：{}", appUser.getNickname());
        log.info("查询设备详情的封装的联系人名称2：response.getNickName()：{}",response.getNickName());
        response.setAvatar(appUser.getAvatar());
        log.info("查询设备详情的封装的最终结果：response：{}",response);
        return response;
    }


    /**
     * 用户端分页查询设备信息
     *
     * @param request 查询参数
     * @return
     */
    public DevicePageResponse userPageList(PetQueryRequest request) {
        int currentPage = 1;
        int pageSize = 10;
        if (request.getCurrentPage() != null) {
            currentPage = request.getCurrentPage();
        }
        if (request.getPageSize() != null) {
            pageSize = request.getPageSize();
        }
        //获取用户信息
        AppUser user = AppTokenUtil.getAppUser();
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        Long userId = user.getAppUserId();
        log.info("用户信息：{}", user);
        String avatar = user.getAvatar();
        //String keyword = request.getKeyword();
        Long groupId = request.getGroupId();

        Set<Long> finalDeviceIds = getDeviceSets(null, userId,groupId);
        DevicePageResponse pageResponse = new DevicePageResponse();
        if (CollectionUtils.isEmpty(finalDeviceIds)) {
            //throw new RuntimeException("当前用户没有绑定任何设备");
            pageResponse.setRecords(new ArrayList<>());
            pageResponse.setOnlineCount(0);
            pageResponse.setOfflineCount(0);
            pageResponse.setTotal(0);
            pageResponse.setPages(0);
            pageResponse.setCurrent(currentPage);
            pageResponse.setSize(pageSize);
            return pageResponse;
        }
        //构建查询条件
        LambdaQueryWrapper<DeviceInfo> queryDeviceInfo = Wrappers.lambdaQuery();

        queryDeviceInfo.in(DeviceInfo::getDeviceId, finalDeviceIds);
        Page<DeviceInfo> page = deviceInfoService.page(new Page<>(currentPage, pageSize), queryDeviceInfo);

        long total = page.getTotal();

        //设备组下的设备总数
        pageResponse.setTotal(total);

        pageResponse.setSize(page.getSize());
        pageResponse.setPages(page.getPages());
        pageResponse.setCurrent(page.getCurrent());
        pageResponse.setOptimizeCountSql(page.optimizeCountSql());
        List<DeviceInfo> deviceInfoList = page.getRecords();
        if (CollectionUtils.isEmpty(deviceInfoList)) {
            pageResponse.setRecords(new ArrayList<>());
            pageResponse.setOnlineCount(0);
            pageResponse.setOfflineCount(0);
            pageResponse.setTotal(0);
            pageResponse.setPages(0);
            pageResponse.setCurrent(currentPage);
            pageResponse.setSize(pageSize);
            return pageResponse;
        }
        //运动中的设备个数
        int online =(int) deviceInfoList.stream().filter(deviceInfo -> deviceInfo.getDeviceStatus().equals(DeviceStatusEnum.MOVING.getCode())).count();
        pageResponse.setOnlineCount(online);

        //静止的设备个数
        int staticCount =(int) deviceInfoList.stream().filter(deviceInfo -> deviceInfo.getDeviceStatus().equals(DeviceStatusEnum.STATIC.getCode())).count();
        pageResponse.setStaticCount(staticCount);

        //离线的设备个数
        int offline =(int) deviceInfoList.stream().filter(deviceInfo -> deviceInfo.getDeviceStatus().equals(DeviceStatusEnum.OFFLINE.getCode())).count();
        pageResponse.setOfflineCount(offline);

        //对设备进行条件过滤
        if(request.getDeviceStatus()!= null){
            deviceInfoList = deviceInfoList.stream().filter(deviceInfo -> deviceInfo.getDeviceStatus().equals(request.getDeviceStatus())).collect(Collectors.toList());
        }
        ArrayList<DeviceQueryResponse> arrayList = new ArrayList<>(deviceInfoList.size());
        deviceInfoList.forEach(deviceInfo -> {
            DeviceQueryResponse response = new DeviceQueryResponse();
            //用户头像
            response.setAvatar(avatar);
            //设备信息
            Long deviceId = deviceInfo.getDeviceId();
            response.setDeviceId(deviceId);
            response.setImei(deviceInfo.getImei());
            if(StringUtils.isNotBlank(deviceInfo.getDeviceName())){
            response.setDeviceName(deviceInfo.getDeviceName());
            }else{
                response.setDeviceName(deviceInfo.getImei());
            }

            response.setDeviceStatus(deviceInfo.getDeviceStatus());
            response.setDeviceStatusName(DeviceStatusEnum.getByCode(deviceInfo.getDeviceStatus()).getName());
            response.setContinueTime(DateUtils.timeDistance(new Date(), deviceInfo.getStatusChangeTime()));

            Pet pet = petService.getByDeviceIdAndUserId(deviceId, userId);
            response.setPetType( pet.getPetType());
            response.setPetTypeName(PetTypeEnum.getByCode(pet.getPetType()).getName());

            LocationRealtime one = locationRealtimeService.getLatestLocationByDeviceId(deviceId);
            if (one == null) {
                log.info("设备不在线");
                //throw new RuntimeException("设备不在线");
            }else{
                if (one.getMileage() != null && one.getMileage() > 0) {
                    response.setMileage(one.getMileage());
                } else {
                    response.setMileage(0.00);
                }
                response.setLongitude(one.getLongitude());
                response.setLatitude(one.getLatitude());
                response.setDetailedLocation(one.getDetailedLocation());
            }

            arrayList.add(response);
        });
        pageResponse.setRecords(arrayList);
        return pageResponse;
    }

    /**
     * 查询设备基础信息
     *
     * @param deviceId 设备id
     * @return DeviceQueryResponse 设备基础信息
     */
    public DeviceQueryResponse basicInfo(Long deviceId) {
        //获取当前用户信息
        AppUser user = AppTokenUtil.getAppUser();
        DeviceQueryResponse response = new DeviceQueryResponse();
        response.setDeviceId(deviceId);
        response.setAvatar(user.getAvatar());
        //根据设备id查询设备信息表得到imei
        LambdaQueryWrapper<DeviceInfo> lambdaQuery = Wrappers.lambdaQuery();
        lambdaQuery.eq(DeviceInfo::getDeviceId, deviceId);
        DeviceInfo deviceInfo = deviceInfoService.getOne(lambdaQuery);
        if (deviceInfo == null) {
            throw new RuntimeException("设备不存在");
        }
        response.setImei(deviceInfo.getImei());
        //查询pet表信息
        Pet pet = petService.getByDeviceIdAndUserId(deviceId, user.getAppUserId());
        if (pet == null) {
            throw new RuntimeException("设备未绑定");
        }
        response.setPetType(pet.getPetType());
        response.setPetTypeName(PetTypeEnum.getByCode(pet.getPetType()).getName());
        //根据设备id查询实时定位表的按照时间倒序的第一条数据
        LocationRealtime one = locationRealtimeService.getLatestLocationByDeviceId(deviceId);
        if (one == null) {
            throw new RuntimeException("设备未定位");
        }
        response.setLatitude(one.getLatitude());
        response.setLongitude(one.getLongitude());
        response.setDetailedLocation(one.getDetailedLocation());
        return response;
    }

    /**
     * 设备首页设备基础信息
     *
     * @param deviceId 设备ID
     * @return DeviceInfoBizResponse
     */
    public DeviceInfoBizResponse homeInfo(Long deviceId) {
        //获取用户信息
        AppUser user = AppTokenUtil.getAppUser();
        if (user == null) {
            throw new RuntimeException("用户信息不存在");
        }
        //头像,deviceId
        String avatar = user.getAvatar();
        DeviceInfoBizResponse response = new DeviceInfoBizResponse();
        response.setDeviceId(deviceId);
        response.setAvatar(avatar);
        //根据deviceId和当前用户得到pet信息的isCollection,petType
        Pet pet = petService.getByDeviceIdAndUserId(deviceId, user.getAppUserId());
        if (pet == null) {
            throw new RuntimeException("用户未绑定该设备");
        }
        response.setIsCollection(pet.getIsCollection());
        response.setPetType(pet.getPetType());
        response.setPetTypeName(PetTypeEnum.getByCode(pet.getPetType()).getName());

        //根据设备id查询设备信息表得到
        LambdaQueryWrapper<DeviceInfo> lambdaQuery = Wrappers.lambdaQuery();
        lambdaQuery.eq(DeviceInfo::getDeviceId, deviceId);
        DeviceInfo deviceInfo = deviceInfoService.getOne(lambdaQuery);
        if (deviceInfo == null) {
            throw new RuntimeException("设备不存在");
        }
        //imei，设备状态，设备状态字符串
        response.setImei(deviceInfo.getImei());
        if(StringUtils.isNotEmpty(deviceInfo.getDeviceName())){
            response.setDeviceName(deviceInfo.getDeviceName());
        }else{
            response.setDeviceName(deviceInfo.getImei());
        }
        response.setBattery(deviceInfo.getBatteryLevel());
        //查询设备实时位置表
        LocationRealtime location = locationRealtimeService.getLatestLocationByDeviceId(deviceId);
        if (location == null) {
            throw new RuntimeException("设备未定位");
        }
        //状态持续时间
        response.setDeviceStatus(deviceInfo.getDeviceStatus());
        response.setDeviceStatusName(DeviceStatusEnum.getByCode(deviceInfo.getDeviceStatus()).getName());
        response.setContinueTime(DateUtils.timeDistance(new Date(), deviceInfo.getStatusChangeTime()));
        BeanUtils.copyProperties(location, response);
        //海拔
        if(location.getAltitude() != null){
            response.setAltitude(location.getAltitude());
        }else{
            response.setAltitude(0.0);
        }
        //卫星数量
        if(location.getSatelliteNum() != null){
            response.setSatelliteNum(location.getSatelliteNum());
        }else{
            response.setSatelliteNum(0);
        }
        response.setLocationTypeName(LocationTypeEnum.getName(location.getLocationType()));
        if (location.getGpsTime() != null) {
            response.setGpsTime(location.getGpsTime());
        } else {
            response.setGpsTime(location.getReceiveTime());
        }
        //设备id查询设备同步设置表得到设备模式
        LambdaQueryWrapper<DeviceSyncSettings> lambdaQuery1 = Wrappers.lambdaQuery();
        lambdaQuery1.eq(DeviceSyncSettings::getDeviceId, deviceId);
        DeviceSyncSettings one = deviceSyncSettingsService.getOne(lambdaQuery1);
        if (one == null) {
            throw new RuntimeException("设备同步设置表不存在");
        }
        response.setDeviceModel(one.getDeviceModel());
        response.setDeviceModeName(DeviceModelEnum.getByCode(one.getDeviceModel()).getName());

        return response;
    }

    public Set<Long> getDeviceSets(String keyword,Long userId,Long groupId){
        Set<Long> finalDeviceIds;

        List<Pet> pets = petService.listByUserId(userId);
        if (CollectionUtils.isEmpty(pets)) {
            return Collections.emptySet();
        }
        Set<Long> deviceIds;
        //如果groupId不为空，过滤得到设备id
        if(groupId != null){
            deviceIds = pets.stream().filter(pet -> pet.getGroupId().equals(groupId)).map(Pet::getDeviceId).collect(Collectors.toSet());
        }else{
            deviceIds = pets.stream().map(Pet::getDeviceId).collect(Collectors.toSet());
        }

        if (StringUtils.isNotBlank(keyword)) {
            //1. 可能关键字是手机号， 则根据手机号模糊查询设备id
            /*Set<Long> phoneDeviceIds = new HashSet<>();
            LambdaQueryWrapper<DeviceSim> lambdaQuery = Wrappers.lambdaQuery();
            lambdaQuery.like(DeviceSim::getPhoneNumber, keyword);
            lambdaQuery.in(DeviceSim::getDeviceId,deviceIds );
            List<DeviceSim> list = deviceSimService.list(lambdaQuery);
            if (!com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(list)) {
                phoneDeviceIds = list.stream().map(DeviceSim::getDeviceId).collect(Collectors.toSet());
            }*/
            //2. 可能关键字是设备号，则从设备表模糊查询获取
            LambdaQueryWrapper<DeviceInfo> lambdaQueryImei = Wrappers.lambdaQuery();
            lambdaQueryImei.like(DeviceInfo::getImei, keyword);
            lambdaQueryImei.in(DeviceInfo::getDeviceId,deviceIds);
            List<DeviceInfo> deviceInfos = deviceInfoService.list(lambdaQueryImei);
            //获取设备id集合
            Set<Long> imeiDeviceIds = new HashSet<>();
            if (!com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(deviceInfos)) {
                imeiDeviceIds = deviceInfos.stream().map(DeviceInfo::getDeviceId).collect(Collectors.toSet());
            }
            //求phoneDeviceIds和imeiDeviceIds的并集
            //finalDeviceIds = Sets.union(phoneDeviceIds, imeiDeviceIds);

            //3.如果关键字是设备名称，则查询设备名称
            LambdaQueryWrapper<DeviceInfo> lambdaQueryName = Wrappers.lambdaQuery();
            lambdaQueryName.like(DeviceInfo::getDeviceName, keyword);
            lambdaQueryName.in(DeviceInfo::getDeviceId,deviceIds);
            List<DeviceInfo> likeDeviceName = deviceInfoService.list(lambdaQueryName);
            Set<Long> nameDeviceIds = new HashSet<>();
            if (!com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(likeDeviceName)) {
                nameDeviceIds = likeDeviceName.stream().map(DeviceInfo::getDeviceId).collect(Collectors.toSet());
            }
            //求finalDeviceIds和nameDeviceIds的并级
            //finalDeviceIds = Sets.union(finalDeviceIds, nameDeviceIds);
            finalDeviceIds = Sets.union(imeiDeviceIds, nameDeviceIds);
        }else {
            finalDeviceIds = deviceIds;
        }
        return finalDeviceIds;
    }



    /**
     * 获取设备ID集合
     * @param keyword 关键字
     * @param userId 用户id
     * @return 设备ID集合
     */
    public Set<Long> getDeviceIds( String keyword,Long userId,Long groupId){
        Set<Long> finalDeviceIds;
        if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(keyword)) {
            Set<Long> deviceIdSet = new HashSet<>();
            //1. 可能关键字是手机号， 则根据手机号模糊查询设备id
            LambdaQueryWrapper<DeviceSim> lambdaQuery = Wrappers.lambdaQuery();
            lambdaQuery.like(DeviceSim::getPhoneNumber, keyword);
            List<DeviceSim> list = deviceSimService.list(lambdaQuery);
            if (!CollectionUtils.isEmpty(list)) {
                deviceIdSet = list.stream().map(DeviceSim::getDeviceId).collect(Collectors.toSet());
            }
            //根据关键字从电话绑定表获取的deviceId集合里可能有不是该用户绑定的设备，所以后面要进行过滤
            if (!CollectionUtils.isEmpty(deviceIdSet)) {
                List<Pet> pets = petService.getByDeviceIdsAndUserId(deviceIdSet, userId);
                if (!CollectionUtils.isEmpty(pets)) {
                    if(groupId != null){
                        //过滤得到符合分组条件的设备id集合
                        deviceIdSet = pets.stream().filter(pet -> pet.getGroupId().equals(groupId)).map(Pet::getDeviceId).collect(Collectors.toSet());
                    } else{
                        deviceIdSet = pets.stream().map(Pet::getDeviceId).collect(Collectors.toSet());
                    }
                }else{
                    deviceIdSet=Collections.emptySet();
                }
            }

            //2. 可能关键字是设备号，则从设备表模糊查询获取
            List<DeviceInfo> deviceInfos = deviceInfoService.listLikeImei(keyword);
            //获取设备id集合
            Set<Long> imeiDeviceIds = new HashSet<>();
            if (!CollectionUtils.isEmpty(deviceInfos)) {
                imeiDeviceIds = deviceInfos.stream().map(DeviceInfo::getDeviceId).collect(Collectors.toSet());
            }
            if (!CollectionUtils.isEmpty(imeiDeviceIds)) {
                List<Pet> pets = petService.getByDeviceIdsAndUserId(imeiDeviceIds, userId);
                if (!CollectionUtils.isEmpty(pets)) {
                    if(groupId!=null){
                        //过滤得到符合分组条件的设备id集合
                        imeiDeviceIds=pets.stream().filter(pet -> pet.getGroupId().equals(groupId)).map(Pet::getDeviceId).collect(Collectors.toSet());
                    }else{
                        imeiDeviceIds = pets.stream().map(Pet::getDeviceId).collect(Collectors.toSet());
                    }
                }else{
                    imeiDeviceIds = Collections.emptySet();
                }
            }
            //求deviceIdSet和imeiDeviceIds的并集
            finalDeviceIds = Sets.union(deviceIdSet, imeiDeviceIds);

            //3.如果关键字是设备名称，则查询设备名称
            List<DeviceInfo> likeDeviceName = deviceInfoService.listLikeDeviceName(keyword);
            Set<Long> nameDeviceIds = new HashSet<>();
            if (!CollectionUtils.isEmpty(likeDeviceName)) {
                nameDeviceIds = likeDeviceName.stream().map(DeviceInfo::getDeviceId).collect(Collectors.toSet());
            }
            if (!CollectionUtils.isEmpty(nameDeviceIds)) {
                List<Pet> pets = petService.getByDeviceIdsAndUserId(nameDeviceIds, userId);
                if (!CollectionUtils.isEmpty(pets)) {
                    if(groupId != null){
                        nameDeviceIds = pets.stream().filter(pet -> pet.getGroupId().equals(groupId)).map(Pet::getDeviceId).collect(Collectors.toSet());
                    }else{
                        nameDeviceIds = pets.stream().map(Pet::getDeviceId).collect(Collectors.toSet());
                    }
                }else{
                    nameDeviceIds = Sets.newHashSet();
                }
            }
            //求finalDeviceIds和nameDeviceIds的并级
            finalDeviceIds = Sets.union(finalDeviceIds, nameDeviceIds);
        } else {
            List<Pet> pets = petService.listByUserId(userId);
            if (CollectionUtils.isEmpty(pets)) {
                finalDeviceIds=Sets.newHashSet();
            }else{
                if(groupId!=null){
                    finalDeviceIds=pets.stream().filter(pet -> pet.getGroupId().equals(groupId)).map(Pet::getDeviceId).collect(Collectors.toSet());
                }else{
                    //获取设备id集合
                    finalDeviceIds = pets.stream().map(Pet::getDeviceId).collect(Collectors.toSet());
                }
            }
        }
        return finalDeviceIds;
    }

    /**
     * 更新设备信息
     * @param request 设备信息请求对象
     */
    @Transactional
    public void updateDeviceInfo(DeviceInfoUpdateRequest request) {
        //获取当前登录用户信息
        AppUser user = AppTokenUtil.getAppUser();
        Long userId = user.getAppUserId();
        //更新设备信息
        LambdaUpdateWrapper<DeviceInfo> wrapperDeviceInfo = Wrappers.lambdaUpdate();
        wrapperDeviceInfo.eq(DeviceInfo::getDeviceId, request.getDeviceId())
                .eq(DeviceInfo::getDataStatus, 1)
                .set(DeviceInfo::getDeviceName, request.getDeviceName());
        deviceInfoService.update(wrapperDeviceInfo);
        //更新用户信息
        LambdaUpdateWrapper<AppUser> wrapperAppUser = Wrappers.lambdaUpdate();
        wrapperAppUser.eq(AppUser::getAppUserId, userId)
                .set(AppUser::getNickname, request.getNickName())
                .set( request.getAvatar()!=null,AppUser::getAvatar, request.getAvatar())
                .set(AppUser::getUpdateTime, new Date());
        if(request.getPetType() != null){
            updatePetType(request.getDeviceId(), request.getPetType());
        }
        //更新redis内容,刷新token
        if(request.getNickName() != null || request.getAvatar() != null){
            LoginAppUser loginAppUser = AppTokenUtil.getLoginAppUser();
            user.setAvatar(request.getAvatar());
            user.setNickname(request.getNickName());
            loginAppUser.setAppUser(user);
            AppTokenUtil.refreshToken(loginAppUser);
        }
        appUserService.update(wrapperAppUser);
    }

    /**
     * 更新宠物类型
     * @param deviceId  设备id
     * @param petType 宠物类型
     * @return
     */
    public void updatePetType(Long deviceId, Integer petType) {
            LambdaUpdateWrapper<Pet> wrapper = Wrappers.lambdaUpdate();
            wrapper.eq(Pet::getDeviceId, deviceId)
                    .eq(Pet::getDataStatus, 1)
                    .set(Pet::getPetType, petType);
                    petService.update(wrapper);
    }

    public List<DeviceSearchResponse> searchDeviceList(String keyword) {
        //获取用户信息
        AppUser user = AppTokenUtil.getAppUser();
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        Long userId = user.getAppUserId();
        log.info("用户信息：{}", user);
        Set<Long> deviceSets = getDeviceSets(keyword, userId, null);
        if (CollectionUtils.isEmpty(deviceSets)) {
            log.info("根据关键字搜索为空,设备id集合：{}", deviceSets);
            return new ArrayList<>();
        }
        log.info("设备id集合：{}", deviceSets);

        List<DeviceInfo> deviceInfos = deviceInfoService.list(new LambdaQueryWrapper<DeviceInfo>().in(DeviceInfo::getDeviceId, deviceSets));
        if (CollectionUtils.isEmpty(deviceInfos)) {
            log.info("设备信息集合：{}", deviceInfos);
            return Collections.emptyList();
        }
        return deviceInfos.stream().map(DeviceSearchResponse::transform).collect(Collectors.toList());
    }
}
